

#include "xmodule_config.h"

#if MODULE_CHECK_ENABLED( MOTOR )

#include <string.h> 

#include "rtl876x.h"
#include "rtl876x_rcc.h"
#include "rtl876x_gpio.h"
#include "rtl876x_tim.h"
#include "rtl876x_pinmux.h"

#include "em_motor.h"
#include "boards.h"

#include "xDLPS.h"

#if MODULE_CHECK_LOG_ENABLED( MOTOR )
#include "log.h"
#define LOG     LOG_INFO
#define LOG0    LOG_INFO0 
#define LOG1    LOG_INFO1
#define LOG2    LOG_INFO2
#define LOG3    LOG_INFO3
#else 
#define LOG(...) 
#define LOG0(...)
#define LOG1(...)
#define LOG2(...)
#define LOG3(...)
#endif 

#define PWM_HIGH_COUNT      (8000 - 1) //(((MOTOR_PWM_PERIOD) * (( MOTOR_PWM_DUTY_CYCLE * 20) / 100)) - 1)
#define PWM_LOW_COUNT       (2000 - 1) //(((MOTOR_PWM_PERIOD) * ((( 100 - 20) * MOTOR_PWM_DUTY_CYCLE) / 100)) - 1)

static uint8_t motor_dlps_index ;

static const T_IO_MODULE_CBS motor_cbs = 
{
    .init = NULL,
    .enter_dlps = em_motor_enter_dlps,
    .exit_dlps = em_motor_exit_dlps,
    .check_allow_dlps = NULL,
    .system_wakeup_check_allow_dlps = NULL,
    .name = "motor\0",
};

static void gpio_configs(void)
{
    Pad_Config( MOTOR_PWM_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_LOW );
    Pinmux_Config( MOTOR_PWM_PIN, MOTOR_PWM_TIMER_PIN_PINMUX ); 
    
    RCC_PeriphClockCmd( APBPeriph_TIMER, APBPeriph_TIMER_CLOCK, ENABLE );
    
    TIM_TimeBaseInitTypeDef timInitStruct;
    
    TIM_StructInit( &timInitStruct );
    timInitStruct.TIM_PWM_En                = PWM_ENABLE;
    timInitStruct.TIM_Mode                  = TIM_Mode_UserDefine;
    timInitStruct.TIM_PWM_High_Count        = PWM_HIGH_COUNT;
    timInitStruct.TIM_PWM_Low_Count         = PWM_LOW_COUNT;
    timInitStruct.TIM_SOURCE_DIV_En         = ENABLE;
    timInitStruct.TIM_SOURCE_DIV            = TIM_CLOCK_DIVIDER_4; // 40M/4 
    TIM_TimeBaseInit( MOTOR_PWM_TIMER_NUM, &timInitStruct );
    TIM_Cmd( MOTOR_PWM_TIMER_NUM, DISABLE );     
}

void em_motor_enter_dlps(void)
{
    Pad_Config( MOTOR_PWM_PIN, PAD_SW_MODE, PAD_NOT_PWRON, PAD_PULL_DOWN, PAD_OUT_DISABLE, PAD_OUT_LOW ); 
}
void em_motor_exit_dlps(void)
{
    Pad_Config( MOTOR_PWM_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_LOW ); 
}

void em_motor_init(void)
{
    gpio_configs();
    
    
}

void em_motor_init_dlps(void)
{
    motor_dlps_index = xDLPS_register( &motor_cbs );
    LOG1("[MOTOR]: DLPS index = %d\r\n", motor_dlps_index );
}

void em_motor_on(void)
{    
    TIM_Cmd( MOTOR_PWM_TIMER_NUM, ENABLE ); 
    xDLPS_set( motor_dlps_index );
}

void em_motor_off(void)
{
    TIM_Cmd( MOTOR_PWM_TIMER_NUM, DISABLE );
    xDLPS_reset( motor_dlps_index );
}


bool em_motor_check_level(uint8_t level)
{
    if( level > LEVEL_OF_MOTOR_ADJUST )
    {
        return false;
    }
    if( (MIN_LEVEL_OF_MOTOR + (STEPS_OF_MOTOR_ADJUST) * level) > MAX_LEVEL_OF_MOTOR)
    {
        return false;
    }

    return true; 
}

void em_motor_set_duty(uint8_t level)
{
    uint32_t high =  (((MOTOR_PWM_PERIOD) * (( MOTOR_PWM_DUTY_CYCLE * level) / 100)) - 1);
    uint32_t low =  (((MOTOR_PWM_PERIOD) * ((( 100 - level) * MOTOR_PWM_DUTY_CYCLE) / 100)) - 1);
    
    if( level == 0 ) 
    {
        high = 1; 
    }
    else if (level == 100 ) 
    {
        low = 1; 
    }
    
    TIM_PWMChangeFreqAndDuty( MOTOR_PWM_TIMER_NUM, high, low ); 
}

#endif // !MODULE_MOTOR_ENABLE

